package com.neardrug.controller;

import com.neardrug.entity.*;
import com.neardrug.mapper.*;
import com.neardrug.services.FileService;
import com.neardrug.system.AsyncTaskFactory;
import com.neardrug.utils.ApiUtil;
import com.neardrug.utils.SpringUtils;
import com.neardrug.vo.MarkdownVO;
import com.neardrug.vo.RecordVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.ssl.SSLContextBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import com.neardrug.common.Constants;
import com.neardrug.common.Result;
import com.neardrug.context.BaseContext;
import com.neardrug.exception.ServiceException;
import io.swagger.annotations.Api;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import cn.hutool.core.io.FileUtil;

import javax.net.ssl.SSLContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;


@RestController
@Api(tags = "文件相关")
@RequestMapping("/files")
@Slf4j
public class FileController {
    @Autowired
    private MarkdownMapper markdownMapper;
    @Autowired
    private RecordMapper recordMapper;
    @Autowired
    private AnalysisMapper analysisMapper;
    @Autowired
    private FileService fileService;
    @Autowired
    private ImagesMapper imagesMapper;
    @Autowired
    private FormImgMapper formImgMapper;
    @Autowired
    private FormTableMapper formTableMapper;


    //定义出文件的目录 其中前者为整个项目的根目录
    private static final String filePath=System.getProperty("user.dir")+"/files/";
    @Value("${fileBaseUrl}")
    private String fileBaseUrl;
    private static final ThreadPoolTaskExecutor EXECUTOR= SpringUtils.getBean("threadPoolTaskExecutor");

    // 创建一个不验证SSL证书的HttpClient
    private static CloseableHttpClient createHttpClient() throws IOException {
        try {
            // 创建一个不验证SSL证书的SSLContext
            SSLContext sslContext = SSLContextBuilder.create()
                    .loadTrustMaterial((chain, authType) -> true) // 允许所有证书
                    .build();

            return HttpClients.custom()
                    .setSSLContext(sslContext)
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) // 不验证主机名
                    .build();
        } catch (Exception e) {
            throw new IOException("Failed to create HttpClient with SSL context", e);
        }
    }

    /**
     * 上传文件然后经过api处理后返回markdown
     * @param file
     * @return
     */
    @PostMapping("/api")
    @ApiOperation("api")
    public Result upload(@RequestParam("file") MultipartFile file) {
        Integer userId = BaseContext.getCurrentId();
        try {
            MarkdownVO markdownVO =AsyncTaskFactory.api(file,userId).get();
            return Result.success(markdownVO);
        } catch (InterruptedException e) {
            throw new ServiceException(Constants.FILE_ERROR,"文件上传过程中线程被中断");
        } catch (ExecutionException e) {
            throw new ServiceException(Constants.FILE_ERROR,"文件分析发生错误");
        } catch (ServiceException e) {
            throw new ServiceException(Constants.API_ERROR,Constants.API_ERROR_MESSAGE);
        }
    }


    /**
     * 根据任务id下载该任务的markdown.md
     */
    @GetMapping("/download/markdown/{taskId}")
    @ApiOperation("下载markdown结果")
    public void download(@PathVariable Integer taskId, HttpServletResponse response) {
        Markdown markdown = markdownMapper.selectByTaskId(taskId);
        String fileName=markdown.getFileName();//不含扩展名
        String markdownResult=markdown.getMarkdown();


        //为fileName加上扩展名用于指定下载文件类型
        fileName=fileName+"-markdown"+".md";
        //将markdownResult转为字节数组作为inputstream
        byte[] markdownResultBytes = markdownResult.getBytes(StandardCharsets.UTF_8);

        try {
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new ServiceException(Constants.FILE_ERROR,"文件错误");
        }
        response.setContentType("application/octet-stream");

        try (InputStream inputStream = new ByteArrayInputStream(markdownResultBytes);
             ServletOutputStream os = response.getOutputStream()) {

            byte[] buffer = new byte[8192]; // 8KB 的缓冲区
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush(); // 刷新输出流
        } catch (IOException e) {
            log.error("文件下载错误:", e);
            //response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 设置错误状态码
            throw new ServiceException(Constants.FILE_ERROR,"文件错误");
        }
    }

    /**
     * 根据任务id下载该任务的著录.json
     */
    @GetMapping("/download/record/{taskId}")
    @ApiOperation("下载著录数据结果")
    public void downloadRecordResult(@PathVariable Integer taskId, HttpServletResponse response) {
        //从recordMapper中查询出文件名称和record内容
        RecordVO recordVO = recordMapper.getRecordByTaskId(taskId);
        String fileName=recordVO.getFileName();//不含扩展名
        Record record=recordVO.getRecord();
        String recordResult=record.getRecordResult();

        //为fileName加上扩展名用于指定下载文件类型
        fileName=fileName+"-著录数据"+".json";
        //将resultResult转为字节数组作为inputstream
        byte[] recordResultBytes = recordResult.getBytes(StandardCharsets.UTF_8);

        try {
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new ServiceException(Constants.FILE_ERROR,"文件错误");
        }
        response.setContentType("application/octet-stream");

        try (InputStream inputStream = new ByteArrayInputStream(recordResultBytes);
             ServletOutputStream os = response.getOutputStream()) {

            byte[] buffer = new byte[8192]; // 8KB 的缓冲区
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush(); // 刷新输出流
        } catch (IOException e) {
            log.error("文件下载错误:", e);
            throw new ServiceException(Constants.FILE_ERROR,"文件错误");
        }
    }

    /**
     * 根据任务id下载该任务的examples.json
     */
    @GetMapping("/download/examples/{taskId}")
    @ApiOperation("下载合成反应结果")
    public void downloadExamplesResult(@PathVariable Integer taskId, HttpServletResponse response) {
        Analysis analysis = analysisMapper.selectByTaskId(taskId);
        String fileName=analysis.getFileName();
        String examplesResult = analysis.getExamplesResult();

        fileName=fileName.substring(0,fileName.indexOf("."));

        //为fileName加上扩展名用于指定下载文件类型
        fileName=fileName+"-examples"+".json";
        //将markdownResult转为字节数组作为inputstream
        byte[] examplesResultBytes = examplesResult.getBytes(StandardCharsets.UTF_8);

        try {
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new ServiceException(Constants.FILE_ERROR,"文件错误");
        }
        response.setContentType("application/octet-stream");

        try (InputStream inputStream = new ByteArrayInputStream(examplesResultBytes);
             ServletOutputStream os = response.getOutputStream()) {

            byte[] buffer = new byte[8192]; // 8KB 的缓冲区
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush(); // 刷新输出流
        } catch (IOException e) {
            log.error("文件下载错误:", e);
            //response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 设置错误状态码
            throw new ServiceException(Constants.FILE_ERROR,"文件错误");
        }
    }

    /**
     * 根据任务id下载该任务的images
     */
    @GetMapping("/download/images/{taskId}")
    @ApiOperation("下载图片页面结果")
    public void downloadImagesResult(@PathVariable Integer taskId,HttpServletResponse response){
        try {
            fileService.downloadImagesResult(taskId,response);
        } catch (Exception e) {
            throw new ServiceException(Constants.CODE_500,"文件下载发送错误");
        }
    }

}
